package leetcode;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

/**
 * 滑动窗口算法
 *
 * @author 王霄
 * @date 2021/9/27 13:29
 **/
public class SlideWindow {

    private static final LinkedList<Long> WINDOW = new LinkedList<>();

    /**
     * 滑动窗口区间大小(毫秒)
     */
    private final long duration;
    /**
     * 区间内允许通过的数量
     */
    private final long count;

    public SlideWindow(long duration, long count) {
        this.duration = duration;
        this.count = count;
    }

    public boolean getSign() {
        synchronized (this) {
            long now = System.currentTimeMillis();
            if (WINDOW.size() < count) {
                return WINDOW.offerLast(now);
            } else if (now - WINDOW.getFirst() > duration) {
                return WINDOW.pollFirst() != null && WINDOW.offerLast(now);
            } else {
                return false;
            }
        }
    }

    public static void main(String[] args) {
        SlideWindow window = new SlideWindow(500, 1);
        new Request("线程A" , window).start();
        new Request("线程B" , window).start();
        new Request("线程C" , window).start();
        new Request("线程D" , window).start();
    }

    /**
     * 模拟请求线程
     */
    public static class Request extends Thread {
        private static final DateTimeFormatter DF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSSSSS");

        private final SlideWindow window;

        public Request(String name, SlideWindow window) {
            super(name);
            this.window = window;
        }

        @Override
        public void run() {
            while (true) {
                if (window.getSign()) {
                    System.out.println(getName() + ": " + DF.format(LocalDateTime.now()));
                } else {
                    try {
                        TimeUnit.MILLISECONDS.sleep(1);
                    } catch (InterruptedException ignored) {
                    }
                }
            }
        }
    }
}
